home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / rayshade / libray / libimage / image.c next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  260 lines

  1. /*
  2.  * image.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Rod G. Bogart, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: image.c,v 4.0 91/07/17 14:33:29 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    image.c,v $
  19.  * Revision 4.0  91/07/17  14:33:29  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include <stdio.h>
  24. #include "libcommon/common.h"
  25. #include "image.h"
  26. #ifdef URT
  27. #include "rle.h"
  28. #endif
  29.  
  30. Image *image_list = NULL;        /* Linked list of images */
  31.  
  32. Image *
  33. ImageCreate(filename)
  34. char *filename;
  35. {
  36.     Image *new;
  37.  
  38.     new = (Image *)Malloc(sizeof(Image));
  39.     new->filename = strsave(filename);
  40.     new->width = 0;
  41.     new->height = 0;
  42.     new->chan = 0;
  43.     new->data = NULL;
  44.     new->next = image_list;
  45.     image_list = new;
  46.     return new;
  47. }
  48.  
  49. Image *
  50. ImageFind(name)
  51. char *name;
  52. {
  53.     Image *im;
  54.  
  55.     for (im = image_list; im; im = im->next) {
  56.         if (strcmp(im->filename, name) == 0)
  57.             return im;
  58.     }
  59.  
  60.     return (Image *)NULL;
  61. }
  62.  
  63. #ifdef URT
  64. Image *
  65. ImageRead(filename)
  66. char *filename;
  67. {
  68.     FILE *fp;
  69.     int i, y, chan;
  70.     rle_hdr in_hdr;
  71.     Image *image;
  72.     rle_pixel **inrows;
  73.  
  74.     /*
  75.      * See if image has been read before.
  76.      */
  77.     image = ImageFind(filename);
  78.     if (image)
  79.         return image;
  80.  
  81.     fp = fopen(filename, "r");
  82.     if (fp == (FILE *)NULL) {
  83.         RLerror(RL_ABORT, "Cannot open RLE file %s.\n",filename);
  84.         return (Image *)NULL;
  85.     }
  86.  
  87.     in_hdr.rle_file = fp;
  88.    
  89.     /* Try to open the RLE file */
  90.     if (rle_get_setup(&in_hdr) < 0) {
  91.         RLerror(RL_ABORT, "Error reading header of %s\n", filename);
  92.         return (Image *)NULL;
  93.     }
  94.  
  95.     /*
  96.      * Read new image
  97.      */
  98.     image = ImageCreate(filename);
  99.  
  100.     in_hdr.xmax -= in_hdr.xmin;
  101.     in_hdr.xmin = 0;
  102.     image->width = in_hdr.xmax + 1;
  103.     image->height = in_hdr.ymax - in_hdr.ymin + 1;
  104.     image->chan = in_hdr.ncolors;
  105.     image->has_alpha = in_hdr.alpha ? 1 : 0;
  106.     image->totalchan = image->chan + image->has_alpha;
  107.     image->chansize = image->width * image->height;
  108.  
  109.     image->data = (unsigned char *) Malloc(
  110.         image->chansize * image->totalchan * sizeof(unsigned char));
  111.  
  112.     /*
  113.      * Allocate array of pointers to pass to rle_getrow.
  114.      */
  115.     inrows = (rle_pixel **)Malloc(image->totalchan *
  116.             sizeof(rle_pixel *));
  117.     /*
  118.      * Set inrows to point to appropriate initial location in image.
  119.      */
  120.     inrows[0] = (rle_pixel *)image->data;
  121.     for (i = 1; i < image->totalchan; i++)
  122.         inrows[i] = inrows[i-1] + image->chansize;
  123.     if (image->has_alpha)
  124.         /* Alpha channel lives in channel -1 */
  125.         inrows++;
  126.  
  127.     /* Read the image */
  128.     for ( y = 0; y < image->height; y++ ) {
  129.         rle_getrow( &in_hdr, inrows );
  130.         /*
  131.          * Update inrows to point to next scanline for
  132.          * each channel.
  133.          */
  134.         for (i = 0; i < image->chan; i++)
  135.             inrows[i] += image->width;
  136.         if (image->has_alpha)
  137.             inrows[-1] += image->width;
  138.     }
  139.  
  140.     (void)fclose(fp);
  141.     return image;
  142. }
  143.  
  144. #else /* !URT */
  145.  
  146. Image *
  147. ImageRead(filename)
  148. char *filename;
  149. {
  150.     FILE *fp;
  151.     char buf[80];
  152.     Image *image;
  153.     int y, x;
  154.     unsigned char *rbuf, *gbuf, *bbuf;
  155.  
  156.     image = ImageFind(filename);
  157.     if (image)
  158.         return image;
  159.  
  160.     fp = fopen(filename, "r");
  161.     if (fp == (FILE *)NULL) {
  162.         RLerror(RL_ABORT, "Cannot open image file %s.\n",filename);
  163.         return (Image *)NULL;
  164.     }
  165.  
  166.     image = ImageCreate(filename);
  167.     /*
  168.      * Read image header.
  169.      */
  170.     if (fgets(buf, 100, fp) == (char *)NULL ||
  171.         sscanf(buf, "%d %d\n", &image->width, &image->height) != 2) {
  172.         RLerror(RL_ABORT, "Cannot read header of image file %s.\n",
  173.             filename);
  174.         fclose(fp);
  175.         return (Image *)NULL;
  176.     }
  177.     /*
  178.      * Generic image files always have 3 channels, no alpha.
  179.      */
  180.     image->chan = image->totalchan = 3;
  181.     image->has_alpha = 0;
  182.     image->chansize = image->width * image->height;
  183.  
  184.     image->data = (unsigned char *) Malloc(
  185.         image->chansize * image->totalchan * sizeof(unsigned char));
  186.  
  187.     rbuf = image->data;
  188.     gbuf = &image->data[image->chansize];
  189.     bbuf = &image->data[image->chansize+image->chansize];
  190.     for (y = 0; y < image->height; y++ ) {
  191.         for (x = 0; x < image->width; x++) {
  192.             *(rbuf++) = getc(fp);
  193.             *(gbuf++) = getc(fp);
  194.             *(bbuf++) = getc(fp);
  195.             if (feof(fp)) {
  196.                 RLerror(RL_ABORT,
  197.                 "Error reading image %s\n",filename);
  198.                 fclose(fp);
  199.                 return (Image *)NULL;
  200.             }
  201.         }
  202.     }
  203.  
  204.     (void)fclose(fp);
  205.     return image;
  206. }
  207. #endif
  208.  
  209. void
  210. ImageIndex(img, ix, iy, fx, fy, smooth, outval)
  211. Image *img;
  212. int ix, iy, smooth;
  213. Float fx, fy;
  214. Float outval[4];
  215. {
  216.     int xplus, yplus, chan, offset;
  217.     Float x0y0, x1y0, x0y1, x1y1;
  218.     unsigned char *data;
  219.  
  220.     if (smooth) {
  221.         /*
  222.          * bi-linear interp of four pixels.  Note this blends
  223.          * the top with the bottom, and the left with the right.
  224.          */
  225.         if (ix == img->width - 1)
  226.             xplus = 1 - img->width;
  227.         else 
  228.             xplus = 1;
  229.         if (iy == img->height - 1)
  230.             yplus = (1 - img->height) * img->width;
  231.         else
  232.             yplus = img->width;
  233.         data = img->data;
  234.         /* compute offset into first channel */
  235.         offset = ix + iy * img->width;
  236.         for (chan = 0; chan < img->totalchan; chan++) {
  237.             x0y0 = (Float)data[offset] / 255.0;
  238.             x1y0 = (Float)data[offset+xplus] / 255.0;
  239.             x0y1 = (Float)data[offset+yplus] / 255.0;
  240.             x1y1 = (Float)data[offset+xplus+yplus]/255.0;
  241.             outval[chan] = (x0y0*(1.0-fx)*(1.0-fy) +
  242.                     x1y0*(fx)*(1.0-fy) +
  243.                     x0y1*(1.0-fx)*(fy) +  x1y1*(fx)*(fy));
  244.             /* Make offset point to next channel */
  245.             offset += img->chansize;
  246.         }
  247.     } else {
  248.         /*
  249.          * Hard edged image pixels (rectangles)
  250.          * Compute offset into first channel
  251.          */
  252.         offset = ix + iy * img->width;
  253.         for (chan = 0; chan < img->totalchan; chan++) {
  254.             outval[chan] = (Float)img->data[offset]/255.0;
  255.             /* Make offset point to next channel */
  256.             offset += img->chansize;
  257.         }
  258.     }
  259. }
  260.